home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * COPYRIGHT 1990,91,92 BY GRACILIS INC.
- *
- * 623 Palace St.
- * Aurora, Il. 60506
- *
- * (708)-801-8800 Office
- * (708)-844-0183 (FAX - Support BBS)
- *
- * GRACILIS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS
- * SOFTWARE FOR ANY PURPOSE.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
- *
- * Permission is granted for non-commercial use/distribution only, as long as
- * this copyright header is included intact and unaltered.
- *
- ******************************************************************************/
-
- /****************************************************************************
- *
- *
- * File: twin_dr.c
- *
- * Rev : 3.0
- *
- * Description:
- *
- * This File contains routines that implement PackeTwin
- * synchronous SCC driver with an interface to KA9Q's TCP/IP suite.
- *
- *
- * Routines:
- *
- * tsync_raw - Applications' routine for transmitting
- * a message via tsync_driver.
- *
- * tsync_stop - Stop I/O
- *
- * tsync_recv - Applications' routine for receiving a message
- * from the tsync_driver. Left over from NET.
- *
- *
- * tsync_hwinit - Initialize the SCC chip for synchronous operation.
- *
- * tsync_txisr - Handles transmit interrupts.
- *
- * tsync_rxisr - Handles receive interrupts.
- *
- * tsync_xstatisr - Handles the SCC's external status interrupts.
- *
- * transon - Turn-on transmitter and turn-off receiver or
- * turn-off transmitter and turn-on receiver.
- * Will change txstate. Also
- * handles time delays needed for data set
- * control signals (RTS).
- *
- *
- * Revision History:
- *
- * Release 2.0 - 9/7/92 First Release of cleaned up Twin driver
- * with fewer files, and called twin_at instead
- * of tsync_at
- *
- * Release 2.1 - 9/12/92 Fix bug in half-duplex dma mode, which caused
- * loss of every other receive frame in a multi-
- * frame transmission.
- */
-
-
- #include <stdio.h>
- #include <dos.h>
- #include "global.h"
- #include "config.h"
- #include "hardware.h"
- #include "mbuf.h"
- #include "iface.h"
- #include "ax25.h"
- #include "trace.h"
- #include "proc.h"
- #include "pktdrvr.h"
- #include "z8530.h"
- #include "gracilis.h"
- #include "twin.h"
-
-
- #ifdef TSYNC_DEBUG
- unsigned char Lastint;
- #endif
-
- #ifdef SCOPE_LOOP
- unsigned char scope_state = 0;
- #endif
-
-
- /* interrupt handler */
- extern INTERRUPT twinvec();
-
- INTERRUPT (*Twin_oldvec) __ARGS((void)); /* Old vector contents */
- INTERRUPT (*Twin_handler) __ARGS((void)) = { twinvec };
-
- char *Twin_dvr_version = "2.1";
- unsigned int Twin_io_base = 0x230;
- int16 Twin_vector;
- int Twin_cputype;
-
- /* The pwait/psignal inter-process communication wake-up array */
- /* for getting pre-allocated receive buffers */
- int Twin_bufpp[5];
-
- /* The pwait/psignal inter-process communication wake-up array */
- /* for kicking the transmitter */
- int Twin_kickpp[5];
-
- /* The pwait/psignal inter-process communication wake-up array */
- /* for free-ing transmitted messages */
- int Twin_freetxpp[5];
-
-
- extern void tsync_txisr();
-
- uchar Twin_sercfg = 0; /* image of the SERIAL_CFG port */
- uchar Twin_dmacfg = 0; /* image of the DMA_CFG port */
-
- /* Master device control blocks for the Tsync drivers... */
- UNI_DCB Twin_udcb[2] = {
- FALSE, 0, NULL, NULL, NULL, NULL, NULL,
- FALSE, 0, NULL, NULL, NULL, NULL, NULL,
- };
-
- /* a simple delay instruction... */
- int nop1;
- #define nop nop1++;
-
- /* Send raw packet */
- int
- tsync_raw(intfp, mbufp)
- register struct iface *intfp;
- register struct mbuf *mbufp;
- {
- register DCB *dcbp;
- register struct drvbuf *xbufp ;
- int16 msgsize;
- char i_state;
- void tsync_txisr();
- int16 len_p();
-
- #ifdef TSYNC_DEBUG_PRT
- int16 pullsize;
- #endif
-
- #ifdef OLD_KA9Q
- dump(intfp, IF_TRACE_OUT, CL_AX25, mbufp);
- #else
- dump(intfp,IF_TRACE_OUT,mbufp);
- #endif
-
- dcbp = (DCB *)Twin_udcb[intfp->dev].dcbp;
-
- /* get packet's transmission size */
- msgsize = len_p(mbufp);
-
- xbufp = (struct drvbuf *)malloc(sizeof(struct drvbuf) + msgsize);
-
- /* If no memory for buffering... then dump the packet on floor */
- /* and return error to caller */
- if(xbufp == (struct drvbuf *)NULL)
- {
- free_p(mbufp);
- return(-1);
- }
-
-
- xbufp->msgsize = msgsize;
- xbufp->next = (struct drvbuf *)NULLBUF;
-
- #ifdef TSYNC_DEBUG_PRT
- if ( (pullsize = dqdata(mbufp, &(xbufp->buf), msgsize+1)) != msgsize )
- { /* somethings wrong. should have gotten all of message */
- printf("tsync_raw error wanted %d bytes pullup-up got only %d\n",
- msgsize, pullsize);
- }
- #else
- /* there will be no check for mismatching msgsize and pullsize */
- dqdata(mbufp, &(xbufp->buf), msgsize);
- #endif
-
- /* now enqueue the message !!! */
- i_state = dirps();
- if ( dcbp->xmtq == (struct drvbuf *)NULLBUF )
- {
- dcbp->xmtq = dcbp->xmtqtail = xbufp;
- }
- else
- {
- dcbp->xmtqtail->next = xbufp;
- dcbp->xmtqtail = xbufp;
- }
-
- /* Note tsync_txisr must be able to run from ISR level as well */
- /* as from "task" level, since tsync_raw is called from task */
- /* level */
-
- /* Only if the transmitter is not doing anything then call it */
-
- if ( dcbp->txstate == IDLE )tsync_txisr(dcbp);
-
- restore(i_state);
-
- return(0);
- }
-
- /*
- * Master interrupt handler. One interrupt at a time is handled.
- * here. Service routines are called from here.
- *
- * This 8530 interrupt handler will take care of both async and
- * sync drivers' interrupts.
- */
-
- /******************************************************/
- /* 85230 Mods: */
- /******************************************************/
- /* NOTE: This interrupt handler is constructed to get */
- /* around a bug in the Zilog 85c230 while */
- /* still allowing use of it's advanced FIFOs */
- /* */
- /* The basic bug is as follows... */
- /* If an interrupt driver is written for the */
- /* 85230, which does NOT make use of the */
- /* automatic vector generation facilities */
- /* provided by RR2, AND..... */
- /* If RR1 is used as the ONLY means of */
- /* identifying the End of a received frame, */
- /* then the 85230 will mis-report the EOF */
- /* when the 1st byte of a CRC is read from */
- /* the receive FIFO, resulting in checking */
- /* the CRC status flag at the wrong time. */
- /* This of course then indicates a CRC */
- /* error, and results in the driver */
- /* discarding an otherwise good frame... */
- /* */
- /* The FIX: */
- /* The Basic idea here is to simulate the */
- /* use of true VECTORED interrupts. */
- /* */
- /* First look for a pending interrupt in */
- /* RR3, then read the VECTOR which would */
- /* have been generated IF we were using */
- /* vectored interrupts. Dispatch to the */
- /* appropriate handler routine. */
- /* */
- /* The reason this approach works is that the */
- /* Special Receive condition interrupt VECTOR */
- /* is not asserted until AFTER the first CRC */
- /* byte is read from the FIFO. This is the */
- /* expected behaviour, and allows the programmer */
- /* to read the second CRC byte, and know that */
- /* he/she may appropriately check the CRC status */
- /* indicator, for the completed frame. */
- /* Additionally, it is known at this point that */
- /* the last two bytes received are the CRC bytes */
- /* which must be discarded, since they are not */
- /* a part of the user data frame. */
- /* */
- /* MORAL: Dont believe RR1's end of received frame */
- /* indication, until you have first waited */
- /* for a SPECIAL RECEIVE CONDITION VECTOR */
- /* to be asserted... or YOU'll be SORRY!!! */
- /******************************************************/
- void
- tsync_entpt()
- {
- register char st;
-
- #ifdef notdef
- char i_state;
- #endif
-
- register DCB *dcbp;
- register int16 ctl;
- register unsigned intreg;
- struct drv_timer *tblk;
- void (*timer_func)();
-
- #ifdef notdef
- i_state = dirps();
- #endif
-
- intreg = inportb( Twin_io_base + INT_REG);
-
- while((intreg & (0x07)) != 0x07 )
- {
-
-
- /* Read interrupt pending register from channel A */
- while(Twin_read_scc( Twin_io_base+SCCA_CMD,R3) != 0 )
- {
- /* Get interrupt vector info from Channel B RR2 */
- st = (Twin_read_scc( Twin_io_base+SCCB_CMD,R2) & 0x0E);
-
- #ifdef TSYNC_DEBUG
- Lastint = st;
- #endif
- switch(st)
- {
- case VEC_CHB_TBE:
- /* Channel B Transmit Int Pending */
- dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
- /* milt tsync_txisr(dcbp); */
- /* Call the Transmit Buffer Empty Handler */
- (*(Twin_udcb[TWINCOMM2].prev_vec2))(dcbp);
- ctl = (int16)(Twin_io_base+SCCB_CMD);
- break;
-
- case VEC_CHB_XTS:
- /* Channel B External Status Int */
- dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
- /* milt tsync_xstatisr(dcbp); */
- /* Call the External Status Change Handler */
- (*(Twin_udcb[TWINCOMM2].prev_vec4))(dcbp);
- ctl = (int16)(Twin_io_base+SCCB_CMD);
- break;
-
- case VEC_CHB_RCAV:
- /* Channel B Rcv Interrupt Pending */
- dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
- /* milt tsync_rxisr(dcbp); */
- /* Call the Receive Character Available Handler */
- (*(Twin_udcb[TWINCOMM2].prev_vec3))(dcbp);
- ctl = (int16)(Twin_io_base+SCCB_CMD);
- break;
-
- case VEC_CHB_SRC:
- /* Channel B Special Rcv Int Pending */
- dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
- /* milt tsync_rxisr(dcbp); */
- /* Call the Special Receive Condition Handler */
- (*(Twin_udcb[TWINCOMM2].prev_vec3))(dcbp);
- ctl = (int16)(Twin_io_base+SCCB_CMD);
- break;
-
- case VEC_CHA_TBE:
- /* Channel A Transmit Int Pending */
- dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
- /* milt tsync_txisr(dcbp); */
- /* Call the Transmit Buffer Empty Handler */
- (*(Twin_udcb[TWINCOMM1].prev_vec2))(dcbp);
- ctl = (int16)(Twin_io_base+SCCA_CMD);
- break;
-
- case VEC_CHA_XTS:
- /* Channel A External Status Int */
- dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
- /* milt tsync_xstatisr(dcbp); */
- /* Call the External Status Change Handler */
- (*(Twin_udcb[TWINCOMM1].prev_vec4))(dcbp);
- ctl = (int16)(Twin_io_base+SCCA_CMD);
- break;
-
- case VEC_CHA_RCAV:
- /* Channel A Rcv Interrupt Pending */
- dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
- /* milt tsync_rxisr(dcbp); */
- /* Call the Receive Character Available Handler */
- (*(Twin_udcb[TWINCOMM1].prev_vec3))(dcbp);
- ctl = (int16)(Twin_io_base+SCCA_CMD);
- break;
-
- case VEC_CHA_SRC:
- /* Channel A Special Rcv Int Pending */
- dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
- /* milt tsync_rxisr(dcbp); */
- /* Call the Special Receive Condition Handler */
- (*(Twin_udcb[TWINCOMM1].prev_vec3))(dcbp);
- ctl = (int16)(Twin_io_base+SCCA_CMD);
- break;
- }
-
- /* Reset highest interrupt under service */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = RES_H_IUS));
- #else
- Twin_write_scc(ctl,R0,RES_H_IUS);
- #endif
- }
-
- if(!(intreg & PKTWIN_TMR1_MSK))
- {
- dcbp = (DCB *)Twin_udcb[TWINCOMM1].dcbp;
- tblk = dcbp->timer1;
- /* Now clear the timer interrupt */
- inportb(Twin_io_base + CLR_TMR1);
-
- /* Now perform the timer's requested function */
- if(tblk->thandler != NULL)
- {
- timer_func = tblk->thandler;
- tblk->thandler = (void (*)())NULL;
- (timer_func)(tblk->targ);
- }
- }
-
-
- if(!(intreg & PKTWIN_TMR2_MSK))
- {
- dcbp = (DCB *)Twin_udcb[TWINCOMM2].dcbp;
- tblk = dcbp->timer1;
- /* Now clear the timer interrupt */
- inportb(Twin_io_base + CLR_TMR2);
-
- /* Now perform the timer's requested function */
- if(tblk->thandler != NULL)
- {
- timer_func = tblk->thandler;
- tblk->thandler = (void (*)())NULL;
- (timer_func)(tblk->targ);
- }
-
- }
-
- intreg = inportb( Twin_io_base + INT_REG);
-
- }
-
- #ifdef notdef
- /* Dont need this... causewe only got here though an int... */
- restore(i_state);
- #endif
- }
-
-
- /*
- * External/Status interrupts caused by a receiver abort,
- * a Transmit UNDERRUN/EOM.
- * SCC enters hunt mode on an abort.
- *
- * On a Transmit Underrun, change state and
- * issue a reset command for it, and return.
- */
- void
- tsync_xstatisr(dcbp)
- register DCB *dcbp;
- {
- register uchar scc_stat,newstat,new_xbits;
-
- /* find out why the external/status interrupt occurred */
- scc_stat = Twin_read_scc(dcbp->zhwmap.ctl,R0);
-
- /* 9/23/91 DGL Try to fix possible race condition */
- /* reset external status latch to enable future changes to catch us */
-
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = RES_EXT_INT));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R0,RES_EXT_INT);
- #endif
-
- new_xbits = scc_stat ^ dcbp->extreg;
-
- /* Check for Tx UNDERRUN/EOM */
- if(new_xbits & TxEOM )
- {
- if(dcbp->dma_flg == TRUE)
- {
- /* Disable this DMA channel */
- outportb(DMAWSMR,dcbp->dma_tx_chan | 0x04);
-
- dcbp->txstate = TX_DONE;
-
- /* update the xmit data tally*/
- dcbp->txbytecnt += dcbp->cur_xbytes;
-
- /* don't allow Underruns to interrupt us */
- Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~0x40));
- /* set the TxEOM bit in the image */
- dcbp->extreg |= TxEOM;
-
-
- /* enable the tx empty interrupt... */
- /* so it can catch us if necessary */
- /* This handles condition where the buffer */
- /* goes empty while we're checking... */
- /* Avoid's a race. 9/23/91 */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0xfb));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R1,0xfb);
- #endif
-
- /* Now check to see if the CRC has already cleared */
- /* the SCC's xmit buffer... */
- newstat = Twin_read_scc(dcbp->zhwmap.ctl,R0);
-
- /* If so, turn off the tx empty interrupt we just enabled */
- /* and process the end of frame condition */
- if(newstat & Tx_BUF_EMP)
- {
- /* Rx and Extern ints on : No Tx ints */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R1,0xf9);
- #endif
-
- tsync_txisr(dcbp);
- }
-
- /* else... it will happen under interrupt ctl */
- /* when the buffer goes empty */
-
- }
-
- else
- {
- /* set the TxEOM bit in the image */
- dcbp->extreg |= TxEOM;
-
-
- if((dcbp->txstate == TX_ACTIVE) || (dcbp->txstate == CRCING))
- {
- dcbp->txstate = TX_DONE;
-
- /* don't allow Underruns to interrupt us */
- Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~0x40));
-
-
- /* if unexpected... bump transmit underrun counts */
- if( dcbp->cur_xbytes > 0 )
- {
- dcbp->txunderun++;
- }
-
- /* enable the tx empty interrupt... */
- /* so it can catch us if necessary */
- /* This handles condition where the buffer */
- /* goes empty while we're checking... */
- /* Avoid's a race. 9/23/91 */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0x13));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R1,0x13);
- #endif
-
- /* check to see if the CRC has already cleared */
- /* the SCC's xmit buffer... */
- newstat = Twin_read_scc(dcbp->zhwmap.ctl,R0);
-
- /* If so, turn off the tx empty interrupt we just enabled */
- /* and process the end of frame condition */
- if(newstat & Tx_BUF_EMP)
- {
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R1,(dcbp->wr1 = 0x11));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R1,0x11);
- #endif
- tsync_txisr(dcbp);
- }
-
- /* else... it will happen under interrupt ctl */
-
- }
- }
-
- }
-
- /* Receive Mode only
- * This triggers when hunt mode is entered, & since an ABORT
- * automatically enters hunt mode, we use that to clean up
- * any waiting garbage
- */
- if(new_xbits & BRK_ABRT )
- {
- if(scc_stat & BRK_ABRT ) dcbp->extreg |= BRK_ABRT;
- else dcbp->extreg &= ~BRK_ABRT;
- dcbp->rxstate = RXABORT;
- dcbp->rxabortcnt++; /* bump aborts */
-
- /* No more Abort interrupts */
- #ifdef notdef
- Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~(0x80)));
- #endif
- if(dcbp->dma_flg == TRUE)
- {
- rxprime_dma(dcbp,0); /* restart for a new frame */
- }
- else
- {
- /* reset err latch */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = ERR_RES));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R0,ERR_RES);
- #endif
- /* read and toss any data */
- inportb(dcbp->zhwmap.data);
- inportb(dcbp->zhwmap.data);
- inportb(dcbp->zhwmap.data);
- inportb(dcbp->zhwmap.data);
-
- /* make sure dcbp->rxbufp has a data buffer to work with!!! */
- dcbp->rxcurp = dcbp->rxbufp->data;
- #ifdef OLD_KA9Q
- dcbp->rxbufp->cnt = sizeof(struct phdr);
- #else
- dcbp->rxbufp->cnt = 0;
- #endif
- /* resync the receiver... */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
- #endif
-
- }
- }
- if(new_xbits & DCD )
- {
- if((scc_stat & DCD) == 0)
- {
- dcbp->extreg &= ~DCD;
- if(dcbp->dma_flg == TRUE)
- {
- rxprime_dma(dcbp,0); /* restart for a new frame */
- }
- else
- {
- /* reset err latch */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0=ERR_RES));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R0,ERR_RES);
- #endif
- /* read and toss any data */
- inportb(dcbp->zhwmap.data);
- inportb(dcbp->zhwmap.data);
- inportb(dcbp->zhwmap.data);
- inportb(dcbp->zhwmap.data);
-
- /* make sure dcbp->rxbufp has a data buffer to work with!!! */
- dcbp->rxcurp = dcbp->rxbufp->data;
- #ifdef OLD_KA9Q
- dcbp->rxbufp->cnt = sizeof(struct phdr);
- #else
- dcbp->rxbufp->cnt = 0;
- #endif
- /* resync the receiver... */
- /* Rx 8 bit/chars, enter hunt mode, CRC enable */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
- #endif
-
- }
- }
- else dcbp->extreg |= DCD;
- }
-
- if(new_xbits & CTS )
- {
- if((scc_stat & CTS) == 0)
- {
- dcbp->extreg &= ~CTS;
-
- dcbp->txctslost++;
-
- if((dcbp->txstate == TX_ACTIVE) || (dcbp->txstate == CRCING))
- {
- dcbp->txstate = TX_DONE;
-
- /* don't allow Underruns to interrupt us */
- Twin_write_scc(dcbp->zhwmap.ctl,R15,(dcbp->wr15 &= ~0x40));
-
-
- /* if unexpected... bump transmit underrun counts */
- if( dcbp->cur_xbytes > 0 )
- {
- dcbp->txunderun++;
- }
-
- /* Toss the frame being sent, and continue... */
- tsync_txisr(dcbp);
-
- }
- }
- else dcbp->extreg |= CTS;
- }
-
- #ifdef notdef /* fix race 9/23/91 */
-
- /* reset external status latch */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R0,(dcbp->wr0 = RES_EXT_INT));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R0,RES_EXT_INT);
- #endif
-
- #endif
-
- return;
- }
- /*
- * end of tsync_xstatisr
- ******************************************************************/
-
-
- /*
- * Receive ISR.
- * The first receive buffer is pre-allocated
- * in the init routine. Thereafter, it is filled here, queued out, and a
- * new one acquired. CRC, OVERRUN and TOOBIG errors merely 'rewind' the
- * pointers and reuse the same buffer.
- */
- void
- tsync_rxisr(dcbp)
- register DCB *dcbp;
- {
- register int16 ctl;
- int16 data;
- struct mbuf *f_dequeavail();
- void tsync_srcisr();
- void empty_scc();
- unsigned char vecmsk;
-
- /* If this channel is a DMA channel handle it elsewhere */
- if(dcbp->dma_flg == TRUE)
- {
- tsync_rxdmaisr(dcbp);
- return;
- }
-
- /* speed up access to 8530 regs */
- ctl = dcbp->zhwmap.ctl;
- data = dcbp->zhwmap.data;
-
-
- /* Get interrupt vector info from Channel B RR2 */
- vecmsk = (Twin_read_scc( Twin_io_base+SCCB_CMD,R2) & 0x0E);
-
- /* If this is an SRC interrupt... handle it that way... */
- if((vecmsk == VEC_CHA_SRC) || (vecmsk == VEC_CHB_SRC))
- {
- tsync_srcisr(dcbp);
- return;
- }
-
-
- /* Check status of receive interrupt */
- if(Twin_read_scc(ctl,R0) & Rx_CH_AV)
- {
-
- /* get char and store it */
- *dcbp->rxcurp++ = inportb(data);
-
- /* tally data byte received */
- dcbp->rxbytecnt++;
-
- /* Allow aborts to get us after we receive a first char */
- #ifdef OLD_KA9Q
- if(dcbp->rxbufp->cnt == sizeof(struct phdr))
- #else
- if(dcbp->rxbufp->cnt == 0)
- #endif
- {
- /* allow Aborts to interrupt us. */
- Twin_write_scc(ctl,R15,(dcbp->wr15 |= 0x80));
- }
-
- /* bump count & check for TOOBIG frames... */
- #ifdef OLD_KA9Q
- if ((++dcbp->rxbufp->cnt) >= (dcbp->rxbufsize+sizeof(struct phdr)))
- #else
- if ((++dcbp->rxbufp->cnt) >= dcbp->rxbufsize)
- #endif
- {
- /* dump buffer - incoming packet is too big */
- dcbp->rxtruncnt++;
-
- /* read all the data out of the rx fifo... */
- /* and TOSS it.. */
- empty_scc(ctl,data);
-
- /* reset buf "pointers" - dump data */
- dcbp->rxcurp = dcbp->rxbufp->data;
- #ifdef OLD_KA9Q
- dcbp->rxbufp->cnt = sizeof(struct phdr);
- #else
- dcbp->rxbufp->cnt = 0;
- #endif
- /* restart the receiver in HUNT MODE... */
- /* to resync it... */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
- #endif
- }
-
- }
-
- return;
- }
- /*
- * end of tsync_rxisr
- ****************************************************************/
-
-
- /****************************************************************/
- /* Special Receive Condition Interrupt Handler... */
- /****************************************************************/
- void
- tsync_srcisr(dcbp)
- register DCB *dcbp;
- {
- unsigned char rx1stat;
- struct mbuf *tmpbufp;
- struct mbuf *f_dequeavail();
- void empty_scc();
- register int16 ctl;
- int16 data;
-
- /* speed up access to 8530 regs */
- ctl = dcbp->zhwmap.ctl;
- data = dcbp->zhwmap.data;
-
- /* Per ZILOG... only read R1 when R0 says there is */
- /* a char waiting... */
- /* get status byte from R1 */
-
- if(Twin_read_scc(ctl,R0) & Rx_CH_AV)
- {
- rx1stat = Twin_read_scc(ctl,R1);
-
- /* empty the 2nd CRC char */
- inportb(data);
-
- /* The End of Frame bit is ALWAYS associated with a character,
- * usually, it is the last CRC char. Only when EOF is true can
- * we look at the CRC byte to see if we have a valid frame
- */
- dcbp->rxpackcnt++;
-
- /* No Abort interrupts */
- Twin_write_scc(ctl,R15,(dcbp->wr15 &= ~(0x80)));
-
- /* END OF FRAME -- Make sure Rx was active */
- if(rx1stat & END_FR)
- {
- /* got a packet - check for CRC error */
- if ( (rx1stat & CRC_ERR) ||
- #ifdef OLD_KA9Q
- (dcbp->rxbufp->cnt < (sizeof(struct phdr) + 10)) )
- #else
- (dcbp->rxbufp->cnt < 10 ) )
- #endif
- {
- /* error occurred; toss frame */
- if (( rx1stat & CRC_ERR ) &&
- #ifdef OLD_KA9Q
- (dcbp->rxbufp->cnt >= (sizeof(struct phdr) + 10)))
- #else
- (dcbp->rxbufp->cnt >= 10) )
- #endif
- dcbp->rxcrcerrcnt++; /* bump CRC errs */
-
- /* read all data out of the rx fifo...*/
- /* and TOSS it.. */
- empty_scc(ctl,data);
-
- /* reusing the old data buffer "dumps" the data */
-
- /* restart the receiver in HUNT MODE... */
- /* to resync it... */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
- #endif
- }
- else
- {
- /* Got a valid packet !! */
-
- /* get next buffer */
- tmpbufp = f_dequeavail(&dcbp->rxavailq, &dcbp->rxavailcount);
-
- if ( tmpbufp != NULLBUF )
- {
-
- /* dump crc bytes, i.e. '-1' */
- dcbp->rxbufp->cnt -= 1;
-
- /* new for NOS */
- /* adjust for packet header */
- #ifdef OLD_KA9Q
- dcbp->rxbufp->data -= sizeof(struct phdr);
- enqueue(&Hopper, dcbp->rxbufp);
- #else
- net_route(dcbp->iface,dcbp->rxbufp);
- #endif
- /* bump packets rreceived */
- /* successfully */
- dcbp->rxnqued++;
-
- dcbp->rxbufp = tmpbufp;
- }
-
- /* No buffers available... */
- /* re-use old buffer - dump data */
- else dcbp->nobufs++;
-
- /* signal the process which */
- /* allocates the rx buffers */
- psignal(&Twin_bufpp[dcbp->dev],1);
-
- } /* end good packet > 10 long received */
-
- } /* End of FRAME */
-
- /* Not EOF... check for overrun */
- else if (rx1stat & Rx_OVR)
- {
- /* Rx overrun - toss buffer */
- /* reset buffer pointers */
- dcbp->rxovercnt++; /* bump overruns */
-
- /* read all data out of the rx fifo...*/
- /* and TOSS it.. */
- empty_scc(ctl,data);
-
- /* reuse old rx buffer.. */
- /* restart the receiver in HUNT MODE... */
- /* to resync it... */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
- #endif
- }
-
- /* regardless of why we terminating/restarting... */
- /* make sure dcbp->rxbufp has a data buffer!!! */
- dcbp->rxcurp = dcbp->rxbufp->data;
- #ifdef OLD_KA9Q
- dcbp->rxbufp->cnt = sizeof(struct phdr);
- #else
- dcbp->rxbufp->cnt = 0;
- #endif
-
-
- /* reset err latch */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = ERR_RES));
- #else
- Twin_write_scc(ctl,R0,ERR_RES);
- #endif
- }
- }
-
-
-
-
-
- /* read the SCC channel till no more data in receiver... */
- void
- empty_scc(ctl,data)
- int16 ctl,data;
- {
-
- while(Twin_read_scc(ctl,R0) & Rx_CH_AV)
- {
- /* get char and toss it */
- inportb(data);
- }
- }
-
-
- /*
- * DMA Receive ISR.
- * The first receive buffer is pre-allocated
- * in the init routine. Thereafter, it is filled here, queued out, and a
- * new one acquired. CRC, OVERRUN and TOOBIG errors merely 'rewind' the
- * pointers and reuse the same buffer.
- */
- tsync_rxdmaisr(dcbp)
- register DCB *dcbp;
- {
- register int16 ctl;
- register int16 dmacnt;
- char rxstat;
- int16 rxbytecnt;
- struct mbuf *f_dequeavail();
- struct mbuf *tmpbufp;
-
- /* mask off this DMA channel */
- outportb(DMAWSMR,(dcbp->dma_rx_chan | 0x04));
-
- /* speed up access to 8530 regs */
- ctl = dcbp->zhwmap.ctl;
-
- /* Check status of receive interrupt */
- rxstat = Twin_read_scc(ctl,R1); /* get status byte from R1 */
-
- /* clear the DMA byte ptr FF */
- outportb(DMAFFCL,00);
-
- /* Rx overrun - toss data by reusing the buffer */
- if (rxstat & Rx_OVR ) dcbp->rxovercnt++; /* bump overruns */
-
- /* The End of Frame bit is ALWAYS associated with a character,
- * usually, it is the last CRC char. Only when EOF is true can
- * we look at the CRC byte to see if we have a valid frame
- */
-
- /* CRC error occurred; toss frame */
- else if ((rxstat & (CRC_ERR|END_FR)) == (CRC_ERR|END_FR) )
- {
- dcbp->rxpackcnt++;
- dcbp->rxcrcerrcnt++;
- }
- else if( rxstat & END_FR )
- {
- /* Disable further Abort interrupts */
- Twin_write_scc(ctl,R15,(dcbp->wr15 &= ~(0x80)));
-
- dcbp->rxpackcnt++;
-
- /* calculate # of bytes received less CRC */
- dmacnt = inportb(dcbp->dma_rx_cnt_reg);
- dmacnt += (inportb(dcbp->dma_rx_cnt_reg) << 8);
-
-
- rxbytecnt = (dcbp->rxbufsize-1) - dmacnt;
-
- dcbp->rxbufp->cnt += rxbytecnt;
-
- /* # of data bytes received... Not including CRC's */
- dcbp->rxbytecnt += rxbytecnt-2;
-
- /* Make sure Rx was active */
- #ifdef OLD_KA9Q
- if ( dcbp->rxbufp->cnt > sizeof(struct phdr) )
- #else
- if ( dcbp->rxbufp->cnt > 0)
- #endif
- { /* then bytes have been received */
-
- #ifdef OLD_KA9Q
- if ( dcbp->rxbufp->cnt >= (sizeof(struct phdr)+10) )
- #else
- if ( dcbp->rxbufp->cnt >= 10 )
- #endif
- {
- /* Got a valid packet !! */
-
- /* get next buffer */
- tmpbufp = f_dequeavail(&dcbp->rxavailq, &dcbp->rxavailcount);
-
- if ( tmpbufp != NULLBUF )
- {
-
- /* dump crc bytes, i.e. '-2' */
- dcbp->rxbufp->cnt -= 2;
- /* new for NOS */
- /* adjust for packet header */
- #ifdef OLD_KA9Q
- dcbp->rxbufp->data -= sizeof(struct phdr);
- enqueue(&Hopper, dcbp->rxbufp);
- #else
- net_route(dcbp->iface,dcbp->rxbufp);
- #endif
- /* bump packets rreceived */
- /* successfully */
- dcbp->rxnqued++;
-
- dcbp->rxbufp = tmpbufp;
- }
-
- /* No buffers available... */
- /* re-use old buffer - dump data */
- else dcbp->nobufs++;
-
- /* signal the process which */
- /* allocates the rx buffers */
- psignal(&Twin_bufpp[dcbp->dev],1);
-
- } /* end good packet > 10 long received */
-
- } /* received frame with > 0 chars */
-
- } /* end END_FR check */
-
- rxprime_dma(dcbp,0);
-
- return;
- }
- /*
- * end of tsync_rxdmaisr
- ****************************************************************/
-
-
- /***********************************************************/
- /* 9/12/92 {dgl} Added "rxinit" arg to allow the caller to */
- /* specify whether or not to "re-enable" the receiver. */
- /* This fixed loss of back to back packets in hdx dma mode */
- /* See bug description in version history */
- /***********************************************************/
- rxprime_dma(dcbp,rxinit)
- register DCB *dcbp;
- int rxinit;
- {
- register int16 ctl;
- ulong realaddr;
- unsigned page;
-
- /* speed up access to 8530 regs */
- ctl = dcbp->zhwmap.ctl;
-
- /* make sure dcbp->rxbufp has data!!! */
- dcbp->rxcurp = dcbp->rxbufp->data;
- #ifdef OLD_KA9Q
- dcbp->rxbufp->cnt = sizeof(struct phdr);
- #else
- dcbp->rxbufp->cnt = 0;
- #endif
- /* reset any errors... */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = ERR_RES));
- #else
- Twin_write_scc(ctl,R0,ERR_RES);
- #endif
- /* Reprime the dma pump... */
-
- /* A rendition of an absolute address for the ptr */
- realaddr = ((ulong)FP_SEG(dcbp->rxcurp) << 4) +
- (ulong)FP_OFF(dcbp->rxcurp);
-
- /* DMA page reg for 8237 */
- page = realaddr >> 16;
-
- outportb(dcbp->dma_rx_pagereg,page); /* setup 64k page */
-
-
- /* mode setup required if we are in HDX operation */
- if(dcbp->hduplex == TRUE)
- {
- outportb(DMAMODE,dcbp->dma_rx_chan | RX_DMA);
- outportb(Twin_io_base+DMA_CFG,dcbp->dma_rx_mode);
- }
-
- /* clear the DMA byte ptr FF */
- outportb(DMAFFCL,00);
-
- /* Max xfer count setup */
- outportb(dcbp->dma_rx_cnt_reg,dcbp->rxbufsize-1);
- outportb(dcbp->dma_rx_cnt_reg,((dcbp->rxbufsize-1)>>8));
-
- /* destination buffer address */
- outportb(dcbp->dma_rx_addr_reg,(realaddr & 0xff));
- outportb(dcbp->dma_rx_addr_reg,((realaddr >> 8) & 0xff));
-
- /* If we are in DMA mode/Half duplex: Turn on the recvr */
- /* Rx 8 bit/chars, enter hunt mode, CRC enable */
- /* Autoenables... */
- if((dcbp->hduplex == TRUE) && (rxinit))
- #ifdef TSYNC_DEBUG
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xf9));
- #else
- Twin_write_scc(dcbp->zhwmap.ctl,R3,0xf9);
- #endif
-
- /* Enable this DMA channel */
- outportb(DMAWSMR,dcbp->dma_rx_chan);
- return;
- }
-
-
- /*
- * PackTen's SCC transmit interrupt service routine
- */
- void
- tsync_txisr(dcbp)
- register DCB *dcbp;
- {
- register int16 ctl;
- register struct drvbuf *btemp;
- char i_state;
- void tsync_persist();
- void transon();
- void txprime_dma();
- void time_wait();
-
- #ifdef TSYNC_DEBUG
- int tstbyt_cnt= 0;
- #endif
-
- /* This routine MAY be able to run with ints ENABLED later... */
- /* We need to investigate... milt / {dgl} */
- /* NEVER NEVER NEVER!!!!!!!!! */
- i_state = dirps();
-
- /* speedup access to 8530 regs */
- ctl = dcbp->zhwmap.ctl;
-
- switch (dcbp->txstate) {
-
- case TX_ACTIVE:
-
- /* Here we are actively sending a frame */
- /* We should only hit this case in NON-DMA modes */
-
- /* If there are more bytes to send... */
- if( dcbp->cur_xbytes > 0 )
- {
- /* Try to feed the ESCC/SCC as many bytes as we can */
- while((Twin_read_scc(ctl,R0) & Tx_BUF_EMP) && (dcbp->cur_xbytes > 0))
- {
- /* send next char and bump the pointer */
- outportb(dcbp->zhwmap.data,*dcbp->cur_xbufp++);
-
- /* tally data byte sent */
- dcbp->txbytecnt++;
- dcbp->cur_xbytes--;
- #ifdef TSYNC_DEBUG
- tstbyt_cnt++;
- #endif
- }
-
- #ifdef TSYNC_DEBUG
- if(tstbyt_cnt > dcbp->maxtxbytes)dcbp->maxtxbytes = tstbyt_cnt;
- #endif
- if(dcbp->cur_xbytes <= 0)
- {
-
- /* turn-off the xmission of Abort on underrun */
- /* To allow the CRC to go out */
- #ifdef TSYNC_DEBUG
- if(dcbp->nrzi_flg == TRUE)
- Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
- else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x80));
- #else
- if(dcbp->nrzi_flg == TRUE)
- Twin_write_scc(ctl,R10,0xa0);
- else Twin_write_scc(ctl,R10,0x80);
- #endif
- /* Sent all the data bytes, now send CRCs */
- /* CRCING is a tsync_xstatisr state */
- /* dcbp->txstate = CRCING;
- */
-
- }
- }
-
- #ifdef notdef
- if( dcbp->cur_xbytes > 0 )
- {
-
- /* send next char and bump the pointer */
- outportb(dcbp->zhwmap.data,*dcbp->cur_xbufp++);
-
- /* tally data byte sent */
- dcbp->txbytecnt++;
-
- /* sent a byte */
- if((--dcbp->cur_xbytes) <= 0)
- {
-
- /* turn-off the xmission of Abort on underrun */
- /* To allow the CRC to go out */
- #ifdef TSYNC_DEBUG
- if(dcbp->nrzi_flg == TRUE)
- Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
- else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x80));
- #else
- if(dcbp->nrzi_flg == TRUE)
- Twin_write_scc(ctl,R10,0xa0);
- else Twin_write_scc(ctl,R10,0x80);
- #endif
- /* Sent all the data bytes, now send CRCs */
- /* CRCING is a tsync_xstatisr state */
- /* dcbp->txstate = CRCING;
- */
-
- /* for slow PCs... */
- }
-
- }
- #endif
-
- else
- {
-
- #ifdef TSYNC_DEBUG
- /* reset Tx int pending to allow the */
- /* Underrun/EOM to happen */
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
-
- /* disable tx ints... */
- Twin_write_scc(ctl,R1,(dcbp->wr1 = 0x11));
- #else
- /* reset Tx int pending to allow the */
- /* Underrun/EOM to happen */
- Twin_write_scc(ctl,R0,0x28);
-
- /* disable tx ints... */
- Twin_write_scc(ctl,R1,0x11);
- #endif
-
- /* Sent all the data bytes, now send CRCs */
- /* CRCING is a tsync_xstatisr state */
- dcbp->txstate = CRCING;
-
- }
- break;
-
- case CRCING:
-
- /* reset Tx int pending to allow the */
- /* Underrun/EOM to happen */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
- #else
- Twin_write_scc(ctl,R0,0x28);
- #endif
- break;
-
-
-
- case TX_DONE: /* All done sending a packet... */
-
- tsync_txdone:
-
- /* for slow PCs... reenable the timer ints... */
- if ((Twin_cputype < 2) && (dcbp->baud >= 9600L)) maskon(0);
-
- /* sent a packet */
- dcbp->txpackcnt++;
-
- /* reset Tx int pending */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
- #else
- Twin_write_scc(ctl,R0,0x28);
- #endif
- /* If we were not called by mistake... */
- /* I.E. by an underrun with no current buffer... */
- if(dcbp->xmtq != (struct drvbuf *)NULLBUF)
- {
-
- /* done sending message so move on to next one */
- if ( dcbp->freem == (struct drvbuf *)NULLBUF )
- {
- dcbp->freem = dcbp->xmtq;
- dcbp->xmtq = dcbp->xmtq->next;
- dcbp->freem->next = (struct drvbuf *)NULLBUF;
- }
- else
- {
- btemp = dcbp->xmtq; /* addr of one to free */
- dcbp->xmtq = btemp->next; /* next one TO BE xmitted */
- btemp->next = dcbp->freem; /* one to be freed is queued */
- dcbp->freem = btemp; /* now set free head ptr */
- }
-
- /* signal the process which is supposed to free the */
- /* transmitted message */
- psignal(&Twin_freetxpp[dcbp->dev],1);
-
- }
-
- /* Check NEW xmtq */
- if(dcbp->xmtq == (struct drvbuf *)NULLBUF)
- {
-
- /* no more msgs to send */
- dcbp->xmtqtail = (struct drvbuf *)NULLBUF;
-
- /* take care of SQUELCH DELAY wait for */
- /* flag byte to go out */
- dcbp->txstate = TX_KEYDOWN_DELAY;
-
- #ifdef notdef
- /* shouldn't need this... if we reset the tx ip bit */
- /* Turn off Tx ints */
- if(dcbp->dma_flg == FALSE)Twin_write_scc(ctl,R1,(dcbp->wr1 = 0x11));
- else Twin_write_scc(ctl,R1,(dcbp->wr1 = 0xf9));
-
- #endif
-
- transon(dcbp,OFF);
- }
- else
- {
- /* immediately start sending the next msg */
- dcbp->cur_xbufp = &(dcbp->xmtq->buf);
- dcbp->cur_xbytes = dcbp->xmtq->msgsize;
- txprime_dma(dcbp); /* start sending a frame */
-
- }
- break;
-
- case IDLE: /* Transmitter idle. Find a frame for transmission */
- if ( dcbp->xmtq == (struct drvbuf *)NULLBUF )
- {
- /* totally idle dudes */
-
- /* reset Tx int pending */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
- #else
- Twin_write_scc(ctl,R0,0x28);
- #endif
- break;
- }
- else
- {
- /* point to the next message to send */
- dcbp->cur_xbufp = &(dcbp->xmtq->buf);
- dcbp->cur_xbytes = dcbp->xmtq->msgsize;
-
- dcbp->txstate = DEFER; /* AND FALL THROUGH */
- }
- case DEFER:
-
- /* If we are in HALF-DUPLEX mode, then we must wait */
- /* for a free channel, and be polite about it (ppersist) */
- /* Otherwise just fire up the transmitter... */
-
- if(dcbp->hduplex == TRUE)
- {
-
- /* Check DCD so we don't step on a frame being received */
- /* DCD is ACTIVE LOW on the SCC DCD pin, but the bit in R0 */
- /* is SET when DCD is ACTIVE!! */
-
- #ifdef notdef
- /* This was the way it was released originally... */
- /* I changed it cause I think this is more robust, if we somehow dropped */
- /* an external status event.... We now poll the CD line to determine if */
- /* we can send, and if needed, then we also will re_sync the extrn stats reg */
-
- if(dcbp->extreg & DCD)
- #endif
- if ( (Twin_read_scc(dcbp->zhwmap.ctl,R0) & DCD) != 0 )
- {
-
- /* DGL 9/22/91 */
- /* sync_up the extreg, if it somehow gets out of sync */
- if(!(dcbp->extreg & DCD)) dcbp->extreg |= DCD;
-
-
- #ifdef TSYNC_DEBUG_PRT
- printf("TSYNC_TXISR: Device num %d DEFER state DCD is not right to xmit \n", dcbp->dev);
- #endif
- psignal(&Twin_kickpp[dcbp->dev],1);
- break;
- }
-
- /* DCD is down */
- if ( (dcbp->ioctlparams->persist & 0x00ff) <= (rand() & 0x00ff) )
- { /* then have to wait, be a less persistent */
- dcbp->txstate = TX_PERSIST;
- time_wait(dcbp,dcbp->timer1, dcbp->ioctlparams->slotime, tsync_persist, dcbp);
- break;
- }
-
- } /* end of Half duplex carrier handling... */
-
- /* Raise RTS and start transmiting */
- /* txstate is changed by the routine, but when */
- /* tsync_txisr is called next the state will be KEYED_UP */
- dcbp->txstate = TX_KEYUP_DELAY;
- transon(dcbp,ON);
- break;
-
- case KEYED_UP:
- /* RTS is ACTIVE or in radio terms the radio is keyed */
- /* and transmiting */
-
- txprime_dma(dcbp); /* start sending a frame */
- /* chars will be going out */
- break;
-
-
- default:
- #ifdef TSYNC_DEBUG_PRT
- printf("DEBUG tsync_txisr: invalid txstate, %d \n\r", dcbp->txstate);
- #endif
-
- /* reset Tx int pending */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
- #else
- Twin_write_scc(ctl,R0,0x28);
- #endif
- break;
-
- /* end switch */
- }
-
- restore(i_state);
- return;
- }
-
- void
- txprime_dma(dcbp)
- register DCB *dcbp;
- {
- register int16 ctl;
- ulong realaddr;
- unsigned page;
-
- /* speed up access to 8530 regs */
- ctl = dcbp->zhwmap.ctl;
-
- /* if we are NOT DMA tx driven */
- if(dcbp->dma_flg == FALSE)
- {
-
- /* reset CRC for next frame */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = RES_Tx_CRC));
-
- /* reset Tx int pending */
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
- #else
- Twin_write_scc(ctl,R0,RES_Tx_CRC);
-
- /* reset Tx int pending */
- Twin_write_scc(ctl,R0,0x28);
- #endif
- /* Get First char to send */
- /* send the transmission char and bump the pointer */
-
- outportb(dcbp->zhwmap.data,*dcbp->cur_xbufp++);
-
- dcbp->txstate = TX_ACTIVE;
-
- /* sent one byte */
- dcbp->cur_xbytes--;
-
- #ifdef TSYNC_DEBUG
- /* Rx/Tx and Extern ints on */
- Twin_write_scc(ctl,R1,(dcbp->wr1 = 0x13));
-
- /* Reset Underrun/EOM latch */
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0xc0));
-
- /* turn-on the xmission of Abort on underrun */
- if(dcbp->nrzi_flg == TRUE)Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa4));
- else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x84));
- #else
- /* Rx/Tx and Extern ints on */
- Twin_write_scc(ctl,R1,0x13);
-
- /* Reset Underrun/EOM latch */
- Twin_write_scc(ctl,R0,0xc0);
-
- /* turn-on the xmission of Abort on underrun */
- if(dcbp->nrzi_flg == TRUE)Twin_write_scc(ctl,R10,0xa4);
- else Twin_write_scc(ctl,R10,0x84);
-
- #endif
-
- /* 4/18/91 */
- /* clear the TxEOM bit in the image */
- dcbp->extreg &= ~TxEOM;
-
- /* allow Underruns to interrupt us */
- Twin_write_scc(ctl,R15,(dcbp->wr15 |= 0x40));
-
- /* for slow PCs... mask out the timer ints... */
- /* This will cause the pc to lose time during xmissions... */
- /* but seems only way to make it work at 9600 */
- if ((Twin_cputype < 2) && (dcbp->baud >= 9600L)) maskoff(0);
-
- }
- else
- {
-
- /* Reprime the tx dma pump... */
-
- /* A rendition of an absolute address for ptr */
- realaddr = ((ulong)FP_SEG(dcbp->cur_xbufp) << 4)
- + (ulong)FP_OFF(dcbp->cur_xbufp);
-
- /* Disable this DMA channel */
- outportb(DMAWSMR,dcbp->dma_tx_chan | 0x04);
-
- /* DMA page reg for 8237 */
- page = realaddr >> 16;
-
- /* setup 64k page */
- outportb(dcbp->dma_tx_pagereg,page);
-
- /* mode setup required if we are in HDX */
- if(dcbp->hduplex == TRUE)
- {
- outportb(DMAMODE,dcbp->dma_tx_chan | TX_DMA);
- outportb(Twin_io_base+DMA_CFG,dcbp->dma_tx_mode);
- }
-
- /* clear the DMA byte ptr FF */
- outportb(DMAFFCL,00);
-
- /* Max xfer count setup */
- outportb(dcbp->dma_tx_cnt_reg,dcbp->cur_xbytes-1);
- outportb(dcbp->dma_tx_cnt_reg,((dcbp->cur_xbytes-1)>>8));
-
- /* destination buffer address */
- outportb(dcbp->dma_tx_addr_reg,(realaddr & 0xff));
- outportb(dcbp->dma_tx_addr_reg,((realaddr >> 8) & 0xff));
-
- /* reset CRC for next frame */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = RES_Tx_CRC));
- #else
- Twin_write_scc(ctl,R0,RES_Tx_CRC);
- #endif
- /* Enable this DMA channel */
- outportb(DMAWSMR,dcbp->dma_tx_chan);
- nop;
- nop;
-
- dcbp->txstate = TX_ACTIVE;
-
- /* Reset Underrun/EOM latch */
- #ifdef TSYNC_DEBUG
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0xc0));
- #else
- Twin_write_scc(ctl,R0,0xc0);
- #endif
- /* allow Underruns to interrupt us */
- Twin_write_scc(ctl,R15,(dcbp->wr15 |= 0x40));
-
- /* clear the TxEOM bit in the image */
- dcbp->extreg &= ~TxEOM;
-
- #ifdef TSYNC_DEBUG
- /* Rx and Extern ints on : No Tx ints */
- Twin_write_scc(ctl,R1,(dcbp->wr1 = 0xf9));
-
- /* reset Tx int pending */
- Twin_write_scc(ctl,R0,(dcbp->wr0 = 0x28));
- #else
- /* Rx and Extern ints on : No Tx ints */
- Twin_write_scc(ctl,R1,0xf9);
-
- /* reset Tx int pending */
- Twin_write_scc(ctl,R0,0x28);
- #endif
-
- }
- }
-
- /*
- * Transmit and Receive Control
- * SET Transmit or Receive Mode
- * Set RTS (request-to-send) to modem on Transmit
- */
- void
- transon(dcbp, onoff)
- register DCB *dcbp;
- int16 onoff;
- {
- register int16 ctl;
- void tsync_sqdelay();
- void tsync_txondelay();
- void time_wait();
-
- /* speed-up access to the SCC's control register */
- ctl = dcbp->zhwmap.ctl;
-
- /* Turn on transmitter to send flags */
- if ( onoff == ON )
- {
-
-
- /* If we are in DMA mode/Half duplex: Turn off the recvr */
- /* Rx 8 bit/chars, enter hunt mode, CRC enable */
- #ifdef notdef
- /* NOT needed with autoenables */
- Twin_write_scc(dcbp->zhwmap.ctl,R3,(dcbp->wr3 = 0xd8));
- #endif
-
- /* flags during KEYUP cause the other guy to sync up while */
- /* he sees garbage*/
- #ifdef TSYNC_DEBUG
- if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
- else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x80));
-
- /* Effectively just activate RTS */
- /* Which is used to key the "radio transmitter" */
- Twin_write_scc(dcbp->zhwmap.ctl,R5,(dcbp->wr5 = 0x6b));
-
- #else
- if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,0xa0);
- else Twin_write_scc(ctl,R10,0x80);
-
- /* Effectively just activate RTS */
- /* Which is used to key the "radio transmitter" */
- Twin_write_scc(dcbp->zhwmap.ctl,R5,0x6b);
-
- #endif
- /*
- * Transmitter now on
- */
-
- /* Delay after Tx on */
-
- /* Handle the special case of NO keyup delay... */
- if(dcbp->ioctlparams->xmitdelay == 0)tsync_txondelay(dcbp);
-
- /* otherwise set up the keyup timer... */
- else
- time_wait(dcbp,dcbp->timer1, dcbp->ioctlparams->xmitdelay, tsync_txondelay, dcbp);
-
-
- }
-
- else
- { /* Tx OFF and Rx ON */
-
- /* delay for squelch tail before enable of Rx */
-
- /* Handle the special case of NO keydown delay... */
- if(dcbp->ioctlparams->squelch == 0)tsync_sqdelay(dcbp);
-
- /* otherwise set up the keydown timer... */
- else
- time_wait(dcbp,dcbp->timer1, dcbp->ioctlparams->squelch, tsync_sqdelay, dcbp);
-
- }
- return;
- }
- /*
- * end of transon
- ********************************************************************/
-
- /*
- * Called by the timer isr at an interrupt level.
- * Persist time is up.
- */
- void tsync_persist(dcbp)
- DCB *dcbp;
- {
- /* new for NOS */
-
- /* persist time is up, have NOS process check for transmit */
- /* by changing the driver's transmit state */
- dcbp->txstate = DEFER;
-
-
- /* AND signal the process which is supposed to kick */
- /* the transmitter */
- psignal(&Twin_kickpp[dcbp->dev],1);
-
- return;
- }
-
- /*
- * Called by the timer isr at an interrupt level.
- * Transmitter on delay is up.
- */
- void tsync_txondelay(dcbp)
- DCB *dcbp;
- {
- /* transmiter is ON and can start sending */
- dcbp->txstate = KEYED_UP;
- tsync_txisr(dcbp);
- return;
- }
-
- /*
- * Called by the timer isr at an interrupt level.
- * Squelch delay is up.
- */
- void tsync_sqdelay(dcbp)
- DCB *dcbp;
- {
- register int16 ctl;
-
-
- /* We are going to shut down the "radio" transmitter. */
- /* REGARDLESS of whether we now have a new frame to send */
- /* or not... Because if we DO have more to send, we */
- /* set txstate to DEFER, and let the tsync_recv routine */
- /* kick us off again from the start, and if we don't */
- /* have more to send we go to IDLE mode. */
-
- /* speed-up access to the SCC's control register */
- ctl = dcbp->zhwmap.ctl;
-
- /* Send MARK on IDLE to make sure other guy aborts any trailing */
- /* garbage */
- /* EXCEPT in NRZI... */
- #ifdef TSYNC_DEBUG
- if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,(dcbp->wr10 = 0xa0));
- else Twin_write_scc(ctl,R10,(dcbp->wr10 = 0x88));
-
- Twin_write_scc(ctl,R5,(dcbp->wr5 = 0x68)); /* TX off now */
- /* I.E. drop RTS */
- #else
- if(dcbp->nrzi_flg == TRUE) Twin_write_scc(ctl,R10,0xa0);
- else Twin_write_scc(ctl,R10,0x88);
-
- Twin_write_scc(ctl,R5,0x68); /* TX off now */
- /* I.E. drop RTS */
- #endif
- /* re-prime the dma driver if necessary */
- /* Necessary because we took the SINGLE dma channel away */
- /* and used it to transmit... now give it back to receiver */
-
- if((dcbp->dma_flg == TRUE) && (dcbp->hduplex == TRUE))rxprime_dma(dcbp,1);
-
- /* perhaps while waiting for the squelch delay tsync_raw was */
- /* called and there is a buffer to send */
-
- if ( dcbp->xmtq != (struct drvbuf *)NULLBUF )
- { /* then start the transmit process */
- /* but not at an interrupt level!! */
- /* now when tsync_recv is called, tx_isr will run */
- dcbp->cur_xbufp = &(dcbp->xmtq->buf);
- dcbp->cur_xbytes = dcbp->xmtq->msgsize;
-
- /* new for NOS */
- /* signal the process which is supposed to kick */
- /* the transmitter */
- dcbp->txstate = DEFER;
- psignal(&Twin_kickpp[dcbp->dev],1);
- }
- else
- { /* now only when tsync_raw runs will the transmit */
- /* process go on */
-
- dcbp->txstate = IDLE;
- }
-
- return;
- }
-
-
- /* This is the driver timer service. */
- /* It's resolution is in 1 msec intervals */
-
- void
- time_wait(dcbp,timer,msecs,timerfunc,arg)
- DCB *dcbp;
- struct drv_timer *timer;
- int16 msecs;
- void (*timerfunc)();
- unsigned long arg;
- {
- int16 hrd_addr;
-
- /* calculate the timer counter reg address */
- hrd_addr = Twin_io_base + TMR_CNT1 + dcbp->dev;
-
- timer->thandler = timerfunc;
- timer->targ = arg;
-
- /* start the timer */
- outportb(hrd_addr,(uchar)(msecs & 0xff));
- nop;
- nop;
- outportb(hrd_addr,(uchar)(msecs >> 8));
- nop;
- nop;
- }
-
-
- /***********************************************************
- * GRACILIS - processes to manage buffer maintenance for the
- * PackeTwin synchronous drivers. These processes
- * are used to insure that buffer maintenance is
- * not performed at interrupt time.
- ***********************************************************/
-
- /* This process is used to pre-allocate receive */
- /* buffers for the 8530 synchronous driver to use. */
- void
- tsync_rxavget(dev, p1, p2)
- int dev; /* device number */
- void *p1; /* not used */
- void *p2; /* not used */
- {
- register int16 i_state;
- DCB *dcbp;
- int16 cur_rxavail, min_rxavail;
-
-
- /* killself if device is not attached yet */
- if (dev > 1) /* only support 0 through 1 */
- return;
- else if (Twin_udcb[dev].attached == FALSE)
- return;
-
- for (;;)
- {
-
- /* wait for the driver to signal it needs */
- /* a look at its pre-allocated receive buffers */
- pwait(&Twin_bufpp[dev]);
-
- dcbp = (DCB *)Twin_udcb[dev].dcbp;
-
- i_state = dirps();
-
- cur_rxavail = dcbp->rxavailcount;
- min_rxavail = dcbp->ioctlparams->rxavailbufs;
-
- restore(i_state);
-
-
- /* see if more receive buffers need allocating */
- if ( cur_rxavail < min_rxavail )
- {
- f_getavail(&(dcbp->rxavailq),
- (int16)(min_rxavail - cur_rxavail),
- dcbp->rxbufsize,
- &(dcbp->rxavailcount),
- dcbp->iface, dcbp->dma_flg);
- }
- } /* end of for(;;) loop */
-
- } /* end of tsync_rxavget() */
-
-
-
-
- /* This process is used to periodically kick */
- /* the PackeTwin synchronous driver whenever */
- /* it is in the DEFERED state */
- void
- tsync_txkick(dev, p1, p2)
- int dev; /* device number */
- void *p1; /* not used */
- void *p2; /* not used */
- {
- register DCB *dcbp;
- register bool pwait_null = FALSE; /* 1st time wait for driver's psignal */
- void tsync_txisr();
-
-
- /* killself if device is not attached yet */
- if (dev > 1) /* only support 0 through 1 */
- return;
- else if (Twin_udcb[dev].attached == FALSE)
- return;
-
- for (;;)
- {
-
- /* wait for the driver to signal it needs */
- /* kick */
- if ( pwait_null )
- pwait(NULL); /* have NOS provide */
- /* the delay needed */
- else
- pwait(&Twin_kickpp[dev]);
-
- /* driver control block */
- dcbp = (DCB *)Twin_udcb[dev].dcbp;
-
- /* Test for DEFERED transmit state */
- if (dcbp->txstate == DEFER)
- {
- tsync_txisr(dcbp);
- if ( dcbp->txstate == DEFER )
- pwait_null = TRUE; /* then driver still */
- /* needs a kick */
- else
- pwait_null = FALSE;
- }
-
- } /* end of for(;;) loop */
-
- } /* end of tsync_txkick() */
-
-
-
- /* This process is used to free buffers */
- /* which have been transmitted by the driver. */
- void
- tsync_freetx(dev, p1, p2)
- int dev; /* device number */
- void *p1; /* not used */
- void *p2; /* not used */
- {
- register int16 i_state;
- register DCB *dcbp;
- register struct drvbuf *xbufp, *btemp;
-
-
- /* killself if device is not attached yet */
- if (dev > 4) /* only support 0 through 4 */
- return;
- else if (Twin_udcb[dev].attached == FALSE)
- return;
-
- for (;;)
- {
-
- /* wait for driver to signal that there are transmitted */
- /* messages to be freed */
- pwait(&Twin_freetxpp[dev]);
-
- /* driver control block */
- dcbp = (DCB *)Twin_udcb[dev].dcbp;
-
- /* Do not do memory free-ups while interrupts are */
- /* disabled! Here xbufp is a "to be free'd" */
- /* queue pointer" */
-
- i_state = dirps();
- xbufp = dcbp->freem;
- dcbp->freem = NULLBUF;
- restore(i_state);
-
- /* now free memory of all the xmitted messages */
- while ( xbufp != (struct drvbuf *)NULL )
- {
- btemp = xbufp->next;
- free((char *)xbufp);
- xbufp = btemp;
- }
- } /* end of for(;;) loop */
-
- } /* end of tsync_freetx() */
-
-
-